﻿using HLStock.Common;
using HLStock.MyExcep;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Diagnostics.Eventing.Reader;
using System.Windows.Input;

namespace HLStock.DBAccess
{
    public class DbInstance : IDisposable
    {
        DbConfig config;
        IDbConnection? dbConnection;
        IDbTransaction? dbTransaction;
        static DbInstance? mainInstance;
        static object locker = new object();
        static object locker2 = new object();
        public static DbInstance CreateDefaultInstance()
        {
            lock (locker)
            {
                lock (locker2)
                {
                    if (mainInstance == null)
                    {
                        mainInstance = new DbInstance(DbConfig.Default());
                    }
                    return mainInstance;
                }
            }
        }
        public DbInstance()
        {
            config = DbConfig.Default();
            Open();
        }
        public DbInstance(DbConfig config)
        {
            this.config = config;
            Open();
        }
        public void Open()
        {
            if (dbConnection == null)
            {
                SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder();
                connectionStringBuilder.DataSource = $"{config.server},{config.port}";
                connectionStringBuilder.UserID = config.uid;
                connectionStringBuilder.Password = config.pwd;
                connectionStringBuilder.InitialCatalog = config.database;
                connectionStringBuilder.MultipleActiveResultSets = true;
                dbConnection = new SqlConnection(connectionStringBuilder.ToString());
            }
            if (dbConnection.State == ConnectionState.Closed)
            {
                try
                {
                    dbConnection.Open();
                    MyLogger.Log("数据库[{0}|{1}]已被打开", config.server, config.uid);
                }
                catch (Exception ex)
                {
                    throw new MyDbConnectException(ex.Message, ex);
                }
            }
        }
        public void Close()
        {
            if (dbTransaction != null)
                dbTransaction.Dispose();
            if (dbConnection != null)
            {
                try
                {
                    dbConnection.Close();
                    dbConnection.Dispose();
                    MyLogger.Log("数据库[{0}|{1}]已被关闭", config.server, config.uid);
                }
                catch (Exception ex)
                {
                    throw new MyDbConnectException(ex.Message, ex);
                }
            }
        }
        public IDbCommand MakeQueryCommand(string sqlStr, params KeyValuePair<string, object?>[] p)
        {
            IDbCommand cmd = dbConnection!.CreateCommand();
            cmd.CommandText = sqlStr;
            cmd.Transaction = dbTransaction;
            foreach (var item in p)
            {
                var _p = cmd.CreateParameter();
                _p.ParameterName = item.Key;
                var val = item.Value;
                val = DataAccessUtils.GetQueryVal(val);
                if (val == null)
                {
                    _p.Value = DBNull.Value;
                    _p.DbType = DbType.String;
                    _p.Size = 1;
                }
                else
                {
                    _p.Value = val;
                    if (_p.DbType == DbType.String)
                    {
                        var val_str = val!.ToString();
                        _p.Size = Math.Max(val_str!.ToString()!.Length, 1);
                    }
                    _p.DbType = DataAccessUtils.TypeToDbType(val.GetType());

                }
                cmd.Parameters.Add(_p);
            }
            cmd.Prepare();
            return cmd;
        }

        public void StartTransaction()
        {
            if (dbConnection == null || dbConnection.State != ConnectionState.Open)
            {
                throw new MyDbTransException("无法启动事务，数据库尚未连接");
            }
            try
            {
                dbTransaction = dbConnection.BeginTransaction();
            }
            catch (Exception ex)
            {
                throw new MyDbTransException(ex.Message, ex);
            }
        }
        public void Commit()
        {
            if (dbTransaction != null)
            {
                dbTransaction.Commit();
                dbTransaction.Dispose();
                dbTransaction = null;
            }
        }
        public void Abort()
        {
            if (dbTransaction != null)
            {
                dbTransaction.Rollback();
                dbTransaction.Dispose();
                dbTransaction = null;
            }
        }

        public void Dispose()
        {
            Close();
        }
    }
}